package br.com.mmm.javacenter.framework.configuration;

import java.io.File;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

import org.apache.log4j.Logger;
import org.picocontainer.MutablePicoContainer;
import org.picocontainer.defaults.DefaultPicoContainer;
import org.picocontainer.defaults.SetterInjectionComponentAdapterFactory;

import br.com.mmm.javacenter.framework.annotations.Dao;
import br.com.mmm.javacenter.framework.dao.HibernateUtil;
import br.com.mmm.javacenter.framework.entity.EntidadeBase;
import br.com.mmm.javacenter.framework.reflection.injectors.Injector;
import br.com.mmm.javacenter.framework.view.formatters.Formatter;
import br.com.mmm.javacenter.framework.view.taglib.helper.Render;

public class IocController {
	private static ArrayList<String> files = new ArrayList<String>();
	public static MutablePicoContainer picoSetterContainer = new DefaultPicoContainer(new SetterInjectionComponentAdapterFactory());
	public static MutablePicoContainer picoContainer = new DefaultPicoContainer();
	public static List<Class<? extends EntidadeBase<?>>> entityBeans = new LinkedList<Class<? extends EntidadeBase<?>>>();
	public static List<Class<? extends Injector>> injectorsBeans = new LinkedList<Class<? extends Injector>>();
	public static List<Class<? extends Formatter>> formattersBeans = new LinkedList<Class<? extends Formatter>>();
	public static List<Class<? extends Render>> rendersBeans = new LinkedList<Class<? extends Render>>();
	public static HashMap<String,Class<?>> controllersBeans = new HashMap<String,Class<?>>();
	private static Logger logger = Logger.getLogger(HibernateUtil.class);
	
	public static void loadAll() {
		String[] a = System.getProperty("java.class.path").split(";");
		try {
			Field field = Thread.currentThread().getContextClassLoader().getClass().getDeclaredField("classes");
			field.setAccessible(true);
			Class<?>[] klasses = (Class<?>[]) field.get(Thread.currentThread().getContextClassLoader());
			
			for(Class<?> klass:klasses){
				files.add(klass.getName());
			}
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		for (String c : a) {
			File file = new File(c);
			if (file.isDirectory()) {
				lerClassesDiretorio(file,file);
			}
		}
		
		for (String file :files){
			try {
				Class<?> klass = Thread.currentThread().getContextClassLoader().loadClass(file);
				if (klass.isAnnotationPresent(Dao.class)){
					picoSetterContainer.registerComponentImplementation(klass);
				}
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
			
		}	
	}

	private static void trataArquivo(File dir,File file) {
		if (file.getName().endsWith(".class")){
			String nome = file.getAbsolutePath().substring(dir.getAbsolutePath().length()+1).replaceAll("\\\\", ".");
			files.add(nome.substring(0,nome.length()-6));		
		}
	}

	private static void lerClassesDiretorio(File file,File anterior) {
		File[] files = file.listFiles();
		if (files != null){
			for (File f:files){
				if(f.isDirectory()){
					lerClassesDiretorio(f,anterior);
				}else{
					trataArquivo(anterior,f);
				}
			}
		}
	}

	public static Object getController(String controller) {
		Object componentInstance = picoSetterContainer.getComponentInstance(controllersBeans.get(controller));
		logger.debug(controller + " to " + componentInstance.getClass().getSimpleName() );
		return componentInstance;
	}

}

